/**
 *  Version:     @(#)aio_poll.c    0.1.17 09/10/2006
 *
 *  Authors:     Hailong Xia <hlxxxx@gmail.com>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty
 *  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
 *  the GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General
 *  Public License along with this library; if not, write to the
 *  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 *  Boston, MA 02111-1307  USA
 */

#ifdef HAVE_CONFIG_H
#include "aio_config.h"
#endif

#ifndef HAVE_POLL

#include "aio_poll.h"

#ifdef _WIN32
# include <winsock2.h> /* We consider function select() must be included. */
#else
# include <sys/socket.h>
# ifndef HAVE_SELECT
#   error "Must have either poll() or select()."
# endif
#endif

int
poll(struct pollfd *fdarray, int nfds, int timeout)
{
        struct timeval t2, *t3;
        fd_set rset, wset, eset;
        int i, maxfd, ret;

        maxfd = 0; /* stdin for call select when havenot invalid fd. */
        FD_ZERO (&rset);
        FD_ZERO (&wset);
        FD_ZERO (&eset);

        for (i = 0; i < nfds; i++) {
                if (fdarray[i].fd < 0)
                        continue;

                if (fdarray[i].events & POLLIN)
                        FD_SET (fdarray[i].fd, &rset);

                if (fdarray[i].events & POLLOUT)
                        FD_SET (fdarray[i].fd, &wset);

                FD_SET(fdarray[i].fd, &eset); /* or something */

                if (fdarray[i].fd > maxfd)
                        maxfd = fdarray[i].fd;
        }

        if (timeout < 0) {
                t3 = NULL;
        }
        else {
                t2.tv_sec = timeout / 1000;
                t2.tv_usec = 1000 * (timeout % 1000);
                t3 = &t2;
        }

#ifdef _WIN32  /* Windows doesn't like you to call select() with no sockets */
        if (maxfd == 0) {
                Sleep(timeout);
                return 0;
        }
#endif
        ret = select (maxfd + 1, &rset, &wset, &eset, t3);

        if (ret != -1) {
                for (i = 0; i < nfds; i++) {
                        if (fdarray[i].fd < 0)
                                continue;

                        fdarray[i].revents = 0;
                        if (FD_ISSET(fdarray[i].fd, &rset))
                                fdarray[i].revents |= POLLIN;

                        if (FD_ISSET(fdarray[i].fd, &wset))
                                fdarray[i].revents |= POLLOUT;

                        if (FD_ISSET(fdarray[i].fd, &eset))
                                fdarray[i].revents |= POLLERR; /* or something */
                }
        }
        return ret;
}

#endif /* HAVE_POLL */
